home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / pas / swag / win_os2.swg / 0010_View Windows BMP Files.pas < prev    next >
Pascal/Delphi Source File  |  1993-11-26  |  29KB  |  874 lines

  1. {
  2. -----------------------------------------------------------------------------
  3. Program BMPView;  { by Barry Naujok, 1993, written in TP7 }
  4.         { This information was completely derived on my own (ALL of it). }
  5.         { If there are any errors or omisions, please let me know at ... }
  6.         {          a1357665@cfs01.cc.monash.edu.au                       }
  7.         { Currently only supports 3-256 colours (not monochrome or true colour) }
  8.         { My opinion: As can be seen from decoding a BitMaP, I truly believe }
  9.         {    that Microsoft is a bit backwards! :) (other opinions welcome) }
  10.  
  11. Uses VESA,Crt,Dos,Strings;
  12.  
  13. Const bufsize=32000; { my optimal buffer size, could be bigger for other drives }
  14.                      { Has to be even for the RLE decompression }
  15. Type THeader=Record
  16.        ID    : Word;     { 'BM' for a Windows BitMaP }
  17.        FSize : LongInt;  { Size of file }
  18.        Ver   : LongInt;  { BMP version (?), currently 0 }
  19.        Image : LongInt;  { Offset of image into file }
  20.        Misc  : LongInt;  { Unknown, appears to be 40 for all files }
  21.        Width : LongInt;  { Width of image }
  22.        Height: LongInt;  { Height of image }
  23.        Num   : Word;     { Not sure, possibly number of images or planes (1) }
  24.        Bits  : Word;     { Number of bits per pixel }
  25.        Comp  : LongInt;  { Type of compression, 0 for uncompressed, 1,2 for RLE }
  26.        ISize : LongInt;  { Size of image in bytes }
  27.        XRes  : LongInt;  { X dots per metre (not inches! for US, unbelievable!) }
  28.        YRes  : LongInt;  { Y dots per metre }
  29.        PSize : LongInt;  { Palette size (number of colours) if not zero }
  30.        Res   : LongInt;  { Probably reserved, currently 0 }
  31.      End;  { 54 bytes }
  32.  
  33.      PByte = ^Byte;
  34.  
  35.      TPalette = Record
  36.        b,g,r,x : Byte;   { BMP uses a fourth byte for the palette, not used }
  37.      End;
  38.  
  39. Var  fl     : File;
  40.      header : THeader;
  41.      buffer : PByte;
  42.  
  43. Procedure BlankPalette;
  44. Var pal : Array[0..767] Of Byte;
  45.     r   : Registers;
  46. Begin
  47.   FillChar(pal,768,0);
  48.   r.ax:=$1012;
  49.   r.bx:=0;
  50.   r.cx:=256;
  51.   r.dx:=Ofs(pal);
  52.   r.es:=Seg(pal);
  53.   Intr($10,r);
  54. End;
  55.  
  56. Procedure SetPalette;
  57. Const Pal16:Array[0..15]Of Byte=(0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63);
  58. Var palette : TPalette;  { ^ Actual BIOS palette numbers for 16 colour modes }
  59.     BIOSpal : Array[0..767] Of Byte;
  60.     i       : Byte;
  61.     r       : Registers;
  62. Begin
  63.   For i:=0 To header.PSize-1 Do Begin
  64.     BlockRead(fl,palette,4);
  65.     If header.PSize>16 Then Begin
  66.       BIOSpal[i*3]:=palette.r Shr 2;
  67.       BIOSpal[i*3+1]:=palette.g Shr 2;
  68.       BIOSpal[i*3+2]:=palette.b Shr 2;
  69.     End Else Begin
  70.       BIOSpal[Pal16[i]*3]:=palette.r Shr 2;
  71.       BIOSpal[Pal16[i]*3+1]:=palette.g Shr 2;
  72.       BIOSpal[Pal16[i]*3+2]:=palette.b Shr 2;
  73.     End;
  74.   End;
  75.   r.ax:=$1012;
  76.   r.bx:=0;
  77.   r.cx:=256;
  78.   r.dx:=Ofs(BIOSpal);
  79.   r.es:=Seg(BIOSpal);
  80.   Intr($10,r);
  81. End;
  82.  
  83. Procedure ShowImage256(name:PChar); Assembler;
  84. Var dseg,width,height,bytes,rows,bank,handle,cp:Word;
  85. Asm
  86.         Mov     dseg,ds
  87.         Mov     ax,header.Comp.Word[0]
  88.         Mov     cp,ax
  89.         Mov     ax,header.Width.Word[0]
  90.         Test    ax,1
  91.         Jz      @0I
  92.         Inc     ax  { image is word aligned so adjust width if needed }
  93.   @0I:  Mov     width,ax
  94.         Mov     ax,header.Height.Word[0]
  95.         Mov     height,ax
  96.         Mov     di,ax
  97.         Dec     di
  98.         Mov     ax,VesaMode.Bytes
  99.         Mov     bytes,ax
  100.         Mov     ax,VesaMode.Height
  101.         Mov     rows,ax
  102.         Mov     es,VesaMode.SegA
  103.  
  104.         Mov     ax,$3D00
  105.         Lds     dx,name
  106.         Int     $21                     { Open the file for assembler }
  107.         Mov     ds,dseg                 { Restore the data segment }
  108.         Jc      @Ex
  109.         Mov     handle,ax
  110.  
  111.         Mov     bx,ax
  112.         Mov     ax,$4200
  113.         Mov     cx,header.Image.Word[2]
  114.         Mov     dx,header.Image.Word[0]
  115.         Int     $21                     { Seek to image location }
  116.         Call    @FR
  117.         Jmp     @0N
  118.  
  119.   @FR:  Push    ax
  120.         Push    cx
  121.         Push    dx
  122.         Mov     ds,dseg
  123.         Mov     bx,handle
  124.         Mov     cx,bufsize
  125.         Lds     si,buffer
  126.         Mov     dx,si
  127.         Mov     ah,$3F
  128.         Int     $21
  129.         Mov     bx,ax                   { Bytes left to read from the buffer }
  130.         Pop     dx
  131.         Pop     cx
  132.         Pop     ax
  133.         RetN
  134.  
  135.   @0N:  Mov     ax,bytes
  136.         Mul     di
  137.         Mov     di,ax
  138.         Mov     bank,dx
  139.         Call    @B1                     { Set the last line & bank }
  140.         Mov     dx,width
  141.  
  142.         Cmp     cp,0
  143.         Je      @0S
  144.  
  145.         { RLE bitmap }
  146.   @1S:  Xor     dx,dx                   { Set DX as the width count }
  147.   @10:  Xor     ah,ah                   { Clear upper byte }
  148.         Lodsb                           { Get "index" byte }
  149.         Dec     bx                      { Decrement buffer count }
  150.         Jnz     @11                     { Jump if not empty }
  151.         Call    @FR                     { Reload buffer }
  152.   @11:  Or      al,al
  153.         Jz      @14                     { Jump if following is a string }
  154.         { Repeat byte }
  155.         Mov     cx,ax                   { else "index" is a repeat count }
  156.         Add     dx,cx
  157.         Lodsb                           { Load data to repeat "index" times }
  158.         Dec     bx
  159.         Jnz     @12                     { Jump if buffer isn't empty }
  160.         Call    @FR
  161.   @12:  Stosb                           { Draw byte to screen }
  162.         Or      di,di                   { Check to see if line crosses bank }
  163.         Jnz     @13
  164.         Inc     bank                    { Change bank if crossed }
  165.         Call    @B1
  166.   @13:  Loop    @12                     { Store all repeated bytes }
  167.         Jmp     @10
  168.         { Dump string }
  169.   @14:  Lodsb                           { Load "count", number of bytes in the string }
  170.         Mov     cx,ax
  171.         Add     dx,cx
  172.         Dec     bx
  173.         Jnz     @1T                     { Update buffer count (& buffer contents) }
  174.         Call    @FR
  175.   @1T:  Or      al,al
  176.         Jz      @20
  177.   @15:  Movsb                           { Transfer string to screen }
  178.         Or      di,di
  179.         Jnz     @16                     { bank checking }
  180.         Inc     bank
  181.         Call    @B1
  182.   @16:  Dec     bx                      { Update buffer count, etc }
  183.         Jnz     @17
  184.         Call    @FR
  185.   @17:  Loop    @15                     { Repeat for string }
  186.         Test    al,1                    { See if there was an odd numbered count }
  187.         Jz      @10                     { Jump if even }
  188.         Lodsb                           { Clear extra byte, due to word alignment }
  189.         Dec     bx
  190.         Jnz     @10                     { Update buffer count, etc }
  191.         Call    @FR
  192.         Jmp     @10
  193.   @20:  Sub     di,dx                   { Move screen pointer to start of line }
  194.         Jnc     @21                     { Jump if not crossed bank }
  195.         Dec     bank                    { Update bank if crossed }
  196.         Call    @B1
  197.   @21:  Sub     di,bytes                { Move to screen line above }
  198.         Jnc     @23                     { Jump if not crossed bank }
  199.         Dec     bank                    { Update bank if crossed }
  200.         Call    @B1
  201.   @23:  Dec     height                  { Update line count }
  202.         Jnz     @1S                     { Jump to start if not end of the image }
  203.         Jmp     @Ex                     { Exit if image drawn }
  204.  
  205.         { Un-compressed bitmap }
  206.   @0S:  Mov     cx,dx
  207.         Mov     ax,di
  208.         Add     ax,cx
  209.         Jc      @03                     { Jump if line crosses bank }
  210.         Cmp     bx,cx
  211.         Jle     @03                     { Jump if file buffer will run out }
  212.         Sub     bx,cx                   { Update buffer counter }
  213.         Shr     cx,1
  214.         Jnc     @01
  215.         Movsb
  216.   @01:  Rep     Movsw                   { Show line }
  217.         Sub     di,dx                   { Go to next line (above) }
  218.         Sub     di,bytes
  219.         Jnc     @02
  220.         Dec     bank                    { See if line above is in another bank }
  221.         Call    @B1
  222.   @02:  Dec     height
  223.         Jnz     @0S
  224.         Jmp     @Ex
  225.   @03:  Movsb
  226.         Or      di,di
  227.         Jnz     @04
  228.         Inc     bank
  229.         Call    @B1
  230.   @04:  Dec     bx
  231.         Jnz     @05
  232.         Call    @FR
  233.   @05:  Loop    @03
  234.         Sub     di,dx
  235.         Jnc     @06
  236.         Dec     bank
  237.         Call    @B1
  238.   @06:  Sub     di,bytes
  239.         Jnc     @07
  240.         Dec     bank
  241.         Call    @B1
  242.   @07:  Dec     height
  243.         Jnz     @0S
  244.         Jmp     @Ex
  245.  
  246.  
  247.         { Set bank }
  248.   @B1:  Push    ax
  249.         Push    ds
  250.         Mov     ds,dseg
  251.         Mov     al,vesaon
  252.         Or      al,al
  253.         Jz      @B3
  254.         Push    bx
  255.         Push    dx
  256.         Mov     dx,bank
  257.         Xor     bx,bx
  258.         Mov     ax,64
  259.         Mul     dx
  260.         Div     VesaMode.Gran
  261.         Mov     dx,ax
  262.         Push    dx
  263.         Call    VesaMode.WinFunc
  264.         Pop     dx
  265.         Inc     bx
  266.         Call    VesaMode.WinFunc
  267.         Pop     dx
  268.         Pop     bx
  269.   @B3:  Pop     ds
  270.         Pop     ax
  271.         RetN
  272.   @Ex:  Mov     ds,dseg
  273.         Mov     bx,handle              { Close the file }
  274.         Mov     ah,$3E
  275.         Int     $21
  276. End;
  277.  
  278. Procedure ShowImage16(name:PChar); Assembler;
  279. Var dseg,width,height,bytes,rows,bank,handle,cp,rc,bc:Word;
  280. Asm
  281.         Mov     dseg,ds
  282.         Mov     ax,header.Comp.Word[0]
  283.         Mov     cp,ax
  284.         Mov     ax,header.Width.Word[0]
  285.         Mov     width,ax
  286.         Mov     ax,header.Height.Word[0]
  287.         Mov     height,ax
  288.         Mov     di,ax
  289.         Dec     di
  290.         Mov     ax,VesaMode.Bytes
  291.         Mov     bytes,ax
  292.         Mov     ax,VesaMode.Height
  293.         Mov     rows,ax
  294.         Mov     es,VesaMode.SegA
  295.  
  296.         Mov     ax,$3D00
  297.         Lds     dx,name
  298.         Int     $21                     { Open the file for assembler }
  299.         Mov     ds,dseg                 { Restore the data segment }
  300.         Jc      @Ex
  301.         Mov     handle,ax
  302.  
  303.         Mov     bx,ax
  304.         Mov     ax,$4200
  305.         Mov     cx,header.Image.Word[2]
  306.         Mov     dx,header.Image.Word[0]
  307.         Int     $21                     { Seek to image location }
  308.         Call    @FR
  309.         Jmp     @0N
  310.  
  311.   @FR:  Push    ax
  312.         Push    bx
  313.         Push    cx
  314.         Push    dx
  315.         Mov     ds,dseg
  316.         Mov     bx,handle
  317.         Mov     cx,bufsize
  318.         Lds     si,buffer
  319.         Mov     dx,si
  320.         Mov     ah,$3F
  321.         Int     $21
  322.         Mov     bc,ax                   { Bytes left to read from the buffer }
  323.         Pop     dx
  324.         Pop     cx
  325.         Pop     bx
  326.         Pop     ax
  327.         RetN
  328.  
  329.   @0N:  Mov     ax,bytes
  330.         Mul     di
  331.         Mov     di,ax
  332.         Mov     bank,dx
  333.         Call    @B1                     { Set the last line & bank }
  334.         Mov     dx,$3CE
  335.         Mov     ax,$205
  336.         Out     dx,ax                   { Set Write Mode 2 }
  337.         Mov     ax,$8008                { Initial bit mask }
  338.  
  339.         Cmp     cp,0
  340.         Je      @0S
  341.  
  342.         { RLE bitmap }
  343.   @1S:  Mov     rc,0
  344.         Mov     ax,$8008
  345.   @10:  Xor     ch,ch                   { Clear upper byte }
  346.         Mov     cl,[si]                 { Get "index" byte }
  347.         Inc     si
  348.         Dec     bc                      { Decrement buffer count }
  349.         Jnz     @11                     { Jump if not empty }
  350.         Call    @FR                     { Reload buffer }
  351.   @11:  Or      cl,cl
  352.         Jz      @14                     { Jump if following is a string }
  353.         { Repeat byte }
  354.         Shr     cl,1                    {   Divide the "index" by two }
  355.         Mov     bl,[si]                 { Load data to repeat "index" times }
  356.         Inc     si
  357.         Dec     bc
  358.         Jnz     @12                     { Jump if buffer isn't empty }
  359.         Call    @FR
  360.   @12:  Rol     bl,4
  361.         Out     dx,ax
  362.         Mov     bh,es:[di]
  363.         Mov     es:[di],bl              { Update screen }
  364.         Ror     ah,1
  365.         Jnc     @1B
  366.         Inc     di
  367.         Jnc     @1B
  368.         Inc     bank                    { Change bank if crossed }
  369.         Call    @B1
  370.   @1B:  Out     dx,ax
  371.         Rol     bl,4
  372.         Mov     bh,es:[di]
  373.         Mov     es:[di],bl
  374.         Ror     ah,1
  375.         Jnc     @13
  376.         Inc     di
  377.         Inc     rc
  378.         Jnc     @13
  379.         Inc     bank                    { Change bank if crossed }
  380.         Call    @B1
  381.   @13:  Loop    @12                     { Store all repeated bytes }
  382.         Jmp     @10
  383.         { Dump string }
  384.   @14:  Mov     cl,[si]                 { Load "count", number of bytes in the string }
  385.         Inc     si
  386.         Dec     bc
  387.         Jnz     @1E                     { Update buffer count (& buffer contents) }
  388.         Call    @FR
  389.   @1E:  Or      cl,cl
  390.         Jz      @20
  391.         Shr     cl,1                    { Divide the "count" by 2 }
  392.         Push    cx
  393.   @15:  Mov     bl,[si]
  394.         Inc     si
  395.         Rol     bl,4
  396.         Out     dx,ax
  397.         Mov     bh,es:[di]
  398.         Mov     es:[di],bl
  399.         Ror     ah,1
  400.         Jnc     @1A
  401.         Inc     di
  402.         Jnz     @1A                     { bank checking }
  403.         Inc     bank
  404.         Call    @B1
  405.   @1A:  Out     dx,ax
  406.         Rol     bl,4
  407.         Mov     bh,es:[di]
  408.         Mov     es:[di],bl
  409.         Ror     ah,1
  410.         Jnc     @16
  411.         Inc     di
  412.         Inc     rc
  413.         Jnz     @16
  414.         Inc     bank
  415.         Call    @B1
  416.   @16:  Dec     bc                      { Update buffer count, etc }
  417.         Jnz     @17
  418.         Call    @FR
  419.   @17:  Loop    @15                     { Repeat for string }
  420.         Pop     cx
  421.         Test    cl,1                    { See if there was an odd numbered count }
  422.         Jz      @10                     { Jump if even }
  423.         Mov     cl,[si]                 { Clear extra byte, due to word alignment }
  424.         Inc     si
  425.         Dec     bc
  426.         Jnz     @10                     { Update buffer count, etc }
  427.         Call    @FR
  428.         Jmp     @10
  429.   @20:  Sub     di,rc                   { Move screen pointer to start of line }
  430.         Jnc     @21                     { Jump if not crossed bank }
  431.         Dec     bank                    { Update bank if crossed }
  432.         Call    @B1
  433.   @21:  Sub     di,bytes                { Move to screen line above }
  434.         Jnc     @22                     { Jump if not crossed bank }
  435.         Dec     bank                    { Update bank if crossed }
  436.         Call    @B1
  437.   @22:  Dec     height                  { Update line count }
  438.         Jnz     @1S                     { Jump to start if not end of the image }
  439.         Jmp     @Ex                     { Exit if image drawn }
  440.  
  441.         { Un-compressed bitmap }
  442.   @0S:  Mov     ax,width
  443.         Xor     bx,bx
  444.         Mov     rc,ax                   { Initialize rowcount }
  445.         Mov     ax,$8008
  446.   @02:  Out     dx,ax                   { Update bit mask register }
  447.         Mov     cl,[si]                 { Load a byte (2 pixels) }
  448.         Inc     si                      { Update buffer pointer }
  449.         Dec     bc                      { Updata buffer count }
  450.         Jnz     @03
  451.         Call    @FR                     { Reload buffer if necessary }
  452.   @03:  Ror     cl,4                    { Move 1st pixel in low part of CL }
  453.         Mov     ch,es:[di]              { Load latches }
  454.         Mov     es:[di],cl              { Update latches }
  455.         Ror     ah,1                    { Shift bit mask right a pixel }
  456.         Out     dx,ax                   { Update bit mask register }
  457.         Ror     cl,4                    { Move 2nd pixel in low part of CL }
  458.         Mov     ch,es:[di]              { as above 3 steps }
  459.         Mov     es:[di],cl              { ... }
  460.         Sub     rc,2
  461.         Jle     @04
  462.         Ror     ah,1
  463.         Jnc     @02
  464.         Inc     di
  465.         Inc     bx
  466.         Jnc     @02
  467.         Inc     bank
  468.         Call    @B1
  469.         Jmp     @02
  470.   @04:  Mov     ax,si                   { Discard extra bytes for }
  471.         Mov     cx,4                    { LongInt alignment (?) }
  472.         And     ax,3
  473.         Sub     cx,ax
  474.         And     cx,3
  475.         Add     si,cx
  476.         Sub     bc,cx
  477.         Sub     di,bx
  478.         Jnc     @06
  479.         Dec     bank
  480.         Call    @b1
  481.   @06:  Sub     di,bytes
  482.         Jnc     @07
  483.         Dec     bank
  484.         Call    @b1
  485.   @07:  Dec     height
  486.         Jnz     @0S
  487.         Jmp     @Ex
  488.  
  489.         { Set bank }
  490.   @B1:  Push    ax
  491.         Push    ds
  492.         Mov     ds,dseg
  493.         Mov     al,vesaon
  494.         Or      al,al
  495.         Jz      @B3
  496.         Push    bx
  497.         Push    dx
  498.         Mov     dx,bank
  499.         Xor     bx,bx
  500.         Mov     ax,64
  501.         Mul     dx
  502.         Div     VesaMode.Gran
  503.         Mov     dx,ax
  504.         Push    dx
  505.         Call    VesaMode.WinFunc
  506.         Pop     dx
  507.         Inc     bx
  508.         Call    VesaMode.WinFunc
  509.         Pop     dx
  510.         Pop     bx
  511.   @B3:  Pop     ds
  512.         Pop     ax
  513.         RetN
  514.   @Ex:  Mov     ds,dseg
  515.         Mov     bx,handle              { Close the file }
  516.         Mov     ah,$3E
  517.         Int     $21
  518. End;
  519. Procedure ShowBMP;
  520. Var fn:Array[0..63]Of Char;
  521. Begin
  522.   StrPCopy(fn,ParamStr(1));
  523.   GetMem(buffer,bufsize);
  524.   Case header.PSize Of
  525.     1..16: Begin
  526.          Case header.Width Of
  527.               0..640  : SetMode($12);
  528.             641..800  : SetMode($102);
  529.             801..1024 : SetMode($104);
  530.            1025..9999 : SetMode($106);
  531.          End;
  532.          BlankPalette;
  533.          ShowImage16(fn);
  534.        End;
  535.     17..256: Begin
  536.          Case header.Width Of
  537.               0..320  : SetMode($13);
  538.             321..640  : SetMode($101);
  539.             641..800  : SetMode($103);
  540.             801..1024 : SetMode($105);
  541.            1025..9999 : SetMode($107);
  542.          End;
  543.          BlankPalette;
  544.          ShowImage256(fn);
  545.        End;
  546.   End;
  547.  
  548.   FreeMem(buffer,bufsize);
  549.   SetPalette;
  550.   Sound(660);
  551.   Delay(100);
  552.   Sound(880);
  553.   Delay(50);
  554.   Sound(440);
  555.   Delay(75);
  556.   NoSound;
  557.  
  558.   ReadKey;
  559.   SetMode(3);
  560. End;
  561.  
  562. Procedure SetPSize;
  563. Begin
  564.   If header.PSize=0 Then Case header.Bits Of
  565.     1 : header.PSize:=2;  { These are the only valid bits in a BMP }
  566.     4 : header.PSize:=16;
  567.     8 : header.PSize:=256;
  568.     24: header.PSize:=0;  { A 24 bit image does not have a palette }
  569.   End;
  570. End;
  571.  
  572. Begin
  573.   If ParamCount>0 Then Begin
  574.     Assign(fl,ParamStr(1));
  575.     {$I-}
  576.     Reset(fl,1);
  577.     {$I+}
  578.     If IOResult=0 Then Begin
  579.       BlockRead(fl,header,54);
  580.       If header.ID=$4D42 Then Begin
  581.         SetPSize; { Set the PSize field in the header if not defined }
  582.         Writeln;
  583.         Writeln('Width  . . . . . ',header.Width,' pixels');
  584.         Writeln('Height . . . . . ',header.Height,' pixels');
  585.         Writeln('Bits per Pixel . ',header.Bits);
  586.         Writeln('Palette Size . . ',header.PSize,' colours, ',header.PSize*4,' bytes');
  587.         Write('Compression  . . type ',header.Comp);
  588.         If header.Comp=0 Then Writeln(' (not compressed)')
  589.           Else Writeln(' (RLE)');
  590.         Writeln('Image Offset . . ',header.Image);
  591.         Writeln('Image Size . . . ',header.ISize,' bytes');
  592.         Writeln('X Resolution . . ',header.XRes,' D/m, ',header.XRes*254 Div 10000,' DPI');
  593.         Writeln('Y Resolution . . ',header.YRes,' D/m, ',header.YRes*254 Div 10000,' DPI');
  594.         Writeln;
  595.         If ((header.Width<641)And(header.Height<481)And(header.PSize<17))
  596.            Or((header.Width<321)And(header.Height<201))Or(IsVesa) Then
  597.         If header.PSize>2 Then Begin
  598.           Writeln('Press a key to show the image');
  599.           ReadKey;
  600.           ShowBMP;
  601.         End Else Writeln('Cannot display the image without VESA graphics support');
  602.         Close(fl);
  603.       End Else Writeln('The file is not a Windows BitMaP file');
  604.     End Else Writeln('File not found, try again');
  605.   End Else Writeln('Usage: BMPVIEW <filename>');
  606. End.
  607. -----------------------------------------------------------------------------
  608. Unit VESA;
  609.  
  610. Interface
  611.  
  612. Type ModeList=Array[1..32] Of Word;  { List of VESA mode numbers }
  613.  
  614.      TVesaMode=Record
  615.        Attr     : Word;         { Mode Attributes                   }
  616.        WinA     : Byte;         { Window A attributes               }
  617.        WinB     : Byte;         { Window B attributes               }
  618.        Gran     : Word;         { Window granularity in K bytes     }
  619.        WinSiz   : Word;         { Size of window in K bytes         }
  620.        SegA     : Word;         { Segment address of window A       }
  621.        SegB     : Word;         { Segment address of window B       }
  622.        WinFunc  : Procedure;    { Windows positioning function      }
  623.        Bytes    : Word;         { Number of bytes per line          }
  624.        Width    : Word;         { Number of horizontal pixels       }
  625.        Height   : Word;         { Number of vertical pixels         }
  626.        CharW    : Byte;         { Width of character cell           }
  627.        CharH    : Byte;         { Height of character cell          }
  628.        Planes   : Byte;         { Number of memory planes           }
  629.        Bits     : Byte;         { Number of bits per pixel          }
  630.        nBanks   : Byte;         { Number of banks        (not used) }
  631.        Model    : Byte;         { Memory model type                 }
  632.        Banks    : Byte;         { Size of bank           (not used) }
  633.        Pages    : Byte;         { Number of image pages             }
  634.        Reserved : Byte; { The following are for 15,16,24,32 bit colour modes }
  635.        RedMaskSize   : Byte;    { Size of Red mask in bits          }
  636.        RedFieldPos   : Byte;    { Bit position of LSB of Red mask   }
  637.        GreenMaskSize : Byte;    { Size of Green mask in bits        }
  638.        GreenFieldPos : Byte;    { Bit position of LSB of Green mask }
  639.        BlueMaskSize  : Byte;    { Size of Blue mask in bits         }
  640.        BlueFieldPos  : Byte;    { Bit position of LSB of Blue mask  }
  641.        RsvdMaskSize  : Byte;    { Size of Reserved mask in bits     }
  642.        RsvdFieldPos  : Byte;    { Bit pos. of LSB of Reserved mask  }
  643.        DirColModeInf : Byte;    { Direct Colour mode attributes     }
  644.        Filler   : Array[0..215] Of Byte; { Not used - filler        }
  645.      End;
  646.  
  647.      TVesaInfo=Record
  648.        Signature    : LongInt;   { Signature - "VESA"               }
  649.        Version      : Word;      { VESA Version number              }
  650.        OEMName      : PChar;     { Pointer to manufacturer name     }
  651.        Capabilities : Longint;   { Capabilities       (Not used)    }
  652.        List         : ^ModeList; { Pointer to list of VESA modes    }
  653.        TotalMemory  : Word;      { Number of 64k memory blocks on card }
  654.        Filler       : Array[1..238] of Byte;
  655.      End; { 258 byte size due to bug in the Diamond SpeedStar 24X v1.01 BIOS }
  656.  
  657.  
  658. Var  VesaMode : TVesaMode;
  659.                 { Contains all info needed for drawing on the screen }
  660.      VesaInfo : TVesaInfo;
  661.                 { Contains info on the VESA BIOS Extensions }
  662.  
  663.      vesaon   : Byte;
  664.                 { Specifies whether a VESA mode is on or not      }
  665.  
  666. Function  IsVesa:Boolean;
  667.           { Detects whether VESA support is present }
  668. Procedure GetVesaInfo;
  669.           { Get Information on VESA modes, etc }
  670. Procedure GetVesaModeInfo(md:Word);
  671.           { Get Information on a VESA mode (md) }
  672. Function  SetMode(md:Word):Boolean;
  673.           { Sets a video mode (OEM and VESA) }
  674. Function  GetMode:Word;
  675.           { Returns the current video mode }
  676. Function  SizeOfVideoState:Word;
  677.           { Returns the size of the buffer needed to save the video state }
  678. Procedure SaveVideoState(Var buf);
  679.           { Saves the SVGA video state in the buffer }
  680. Procedure RestoreVideoState(Var buf);
  681.           { Restores the SVGA video state from the buffer}
  682. Procedure SetBank(bank:Word);
  683.           { Set the video bank to draw on }
  684. Function  GetBank:Word;
  685.           { Gets the current active video bank }
  686. Procedure SetLineLength(Var len:Word);
  687.           { Sets the logical scan line length, returns the actual length set }
  688. Function  GetLineLength:Word;
  689.           { Returns the current logical scan line length }
  690. Procedure SetDisplayStart(pixel,line:Word);
  691.           { Sets the first pixel and line on the display }
  692. Procedure GetDisplayStart(Var pixel,line:Word);
  693.           { Returns the first pixel and line on the display }
  694.  
  695. {---------------------------------------------------------------------------}
  696. {-----------------------------} Implementation {----------------------------}
  697. {---------------------------------------------------------------------------}
  698.  
  699. Uses Dos;
  700.  
  701. Var  rp : Registers;
  702.  
  703. Function IsVesa:Boolean;
  704. Begin
  705.   rp.ax:=$4F03;
  706.   Intr($10,rp);
  707.   IsVesa:=(rp.al=$4F);
  708. End;
  709.  
  710. Procedure GetVesaInfo;
  711. Begin
  712.   rp.ax:=$4F00;
  713.   rp.di:=Ofs(VesaInfo);
  714.   rp.es:=Seg(VesaInfo);
  715.   Intr($10,rp);
  716. End;
  717.  
  718. Procedure GetVesaModeInfo(md:Word);
  719. Begin
  720.   rp.ax:=$4F01;
  721.   rp.cx:=md;
  722.   rp.di:=Ofs(VesaMode);
  723.   rp.es:=Seg(VesaMode);
  724.   Intr($10,rp);
  725. End;
  726.  
  727. Function SetMode(md:Word):Boolean;
  728. Begin
  729.   SetMode:=True; vesaon:=1;
  730.   If md>$FF Then Begin
  731.     rp.bx:=md;
  732.     rp.ax:=$4F02;
  733.     Intr($10,rp);
  734.     If rp.ax<>$4F Then SetMode:=False Else GetVesaModeInfo(md);
  735.   End Else Begin
  736.     rp.ax:=md;
  737.     Intr($10,rp);
  738.     VesaMode.Gran:=64; vesaon:=0;
  739.     VesaMode.SegA:=$A000;
  740.     Case md Of  { OEM (standard) video modes }
  741.       1..3,7 : Begin { Text modes }
  742.                  VesaMode.Width:=80;  VesaMode.Height:=25;
  743.                  If md=7 Then Begin
  744.                    VesaMode.Bits:=1;  VesaMode.SegA:=$B000;
  745.                  End Else Begin
  746.                    VesaMode.Bits:=4;  VesaMode.SegA:=$B800;
  747.                  End;
  748.                  VesaMode.Bytes:=160; VesaMode.Model:=0;
  749.                End;
  750.       $13 : Begin  { 320 x 200 x 256 colours, VGA & MCGA }
  751.               VesaMode.Width:=320; VesaMode.Height:=200;
  752.               VesaMode.Bits:=8;    VesaMode.Model:=4;
  753.               VesaMode.Bytes:=320;
  754.             End;
  755.       $12 : Begin  { 640 x 480 x 16 colours, VGA only }
  756.               VesaMode.Width:=640; VesaMode.Height:=480;
  757.               VesaMode.Bits:=4;    VesaMode.Model:=3;
  758.               VesaMode.Bytes:=80;
  759.             End;
  760.       $10 : Begin  { 640 x 350 x 16 colours, VGA & EGA with 128k+ }
  761.               VesaMode.Width:=640; VesaMode.Height:=350;
  762.               VesaMode.Bits:=4;    VesaMode.Model:=3;
  763.               VesaMode.Bytes:=80;
  764.             End;
  765.       $0E : Begin  { 640 x 200 x 16 colours, VGA & EGA }
  766.               VesaMode.Width:=640; VesaMode.Height:=200;
  767.               VesaMode.Bits:=4;    VesaMode.Model:=3;
  768.               VesaMode.Bytes:=80;
  769.             End;
  770.       $0D : Begin  { 320 x 200 x 16 colours, VGA & EGA }
  771.               VesaMode.Width:=320; VesaMode.Height:=200;
  772.               VesaMode.Bits:=4;    VesaMode.Model:=3;
  773.               VesaMode.Bytes:=40;
  774.             End;
  775.       Else SetMode:=False;
  776.     End;
  777.   End;
  778. End;
  779.  
  780. Function GetMode:Word;
  781. Begin
  782.   rp.ax:=$4F03;
  783.   Intr($10,rp);
  784.   GetMode:=rp.bx;
  785. End;
  786.  
  787. Function SizeOfVideoState:Word;
  788. Begin  { Will save/restore all video states }
  789.   rp.ax:=$4F04;
  790.   rp.dl:=0;
  791.   rp.cx:=$0F;  { hardware, BIOS, DAC & SVGA states }
  792.   Intr($10,rp);
  793.   SizeOfVideoState:=rp.bx;
  794. End;
  795.  
  796. Procedure SaveVideoState(Var buf);
  797. Begin
  798.   rp.ax:=$4F04;
  799.   rp.dl:=1;
  800.   rp.cx:=$0F;
  801.   rp.es:=Seg(buf);
  802.   rp.bx:=Ofs(buf);
  803.   Intr($10,rp);
  804. End;
  805.  
  806. Procedure RestoreVideoState(Var buf);
  807. Begin
  808.   rp.ax:=$4F04;
  809.   rp.dl:=2;
  810.   rp.cx:=$0F;
  811.   rp.es:=Seg(buf);
  812.   rp.bx:=Ofs(buf);
  813.   Intr($10,rp);
  814. End;
  815.  
  816. Procedure SetBank(bank:Word);
  817. Var winnum:Word;
  818. Begin
  819.   winnum:=bank*64 Div VesaMode.Gran;
  820.   rp.ax:=$4F05;
  821.   rp.bx:=0;
  822.   rp.dx:=winnum;
  823.   Intr($10,rp);
  824.   rp.ax:=$4F05;
  825.   rp.bx:=1;
  826.   rp.dx:=winnum;
  827.   Intr($10,rp);
  828. End;
  829.  
  830. Function GetBank:Word;
  831. Begin
  832.   rp.ax:=$4F05;
  833.   rp.bx:=$100;
  834.   Intr($10,rp);
  835.   GetBank:=rp.dx;
  836. End;
  837.  
  838. Procedure SetLineLength(Var len:Word);
  839. Begin
  840.   rp.ax:=$4F06;
  841.   rp.bl:=0;
  842.   rp.cx:=len;
  843.   Intr($10,rp); { dx:=maximum number of scan lines }
  844.   len:=rp.cx;
  845. End;
  846.  
  847. Function GetLineLength:Word;
  848. Begin
  849.   rp.ax:=$4F06;
  850.   rp.bl:=1;
  851.   Intr($10,rp); { dx:=maximum number of scan lines }
  852.   GetLineLength:=rp.cx;
  853. End;
  854.  
  855. Procedure SetDisplayStart(pixel,line:Word);
  856. Begin
  857.   rp.ax:=$4F07;
  858.   rp.bx:=0;
  859.   rp.cx:=pixel;
  860.   rp.dx:=line;
  861.   Intr($10,rp);
  862. End;
  863.  
  864. Procedure GetDisplayStart(Var pixel,line:Word);
  865. Begin
  866.   rp.ax:=$4F07;
  867.   rp.bx:=1;
  868.   Intr($10,rp);
  869.   pixel:=rp.cx;
  870.   line:=rp.dx;
  871. End;
  872.  
  873. End.
  874.